package cn.cxl.cxlutils;

import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class RoadRecordService extends Service {
    private static final String TAG = "RoadRecordService";
    //    adb shell am startservice -n .RoadRecordService --ei duration 20000 --ei id 0 --ei height 1080 --ei width 1920
    //    adb shell am stopservice -n .RoadRecordService
    private int video_duration = 10000;
    private int camera_id = 0;
    private int camera_w = 1920;
    private int camera_h = 1080;
    private MediaRecorder mMediaRecorder;
    private WindowManager windowManager;
    private CameraManager cameraManager;
    private CameraDevice cameraDevice;
    private CameraCaptureSession mPreviewSession;
    private CaptureRequest.Builder mPreviewBuilder;
    private CameraDevice.StateCallback mCameraDeviceStateCallback;
    private CameraCaptureSession.StateCallback mSessionStateCallback;
    private CameraCaptureSession.CaptureCallback mSessionCaptureCallback;
    private Handler mChildHandler;
    private int i = 0;
    private boolean isClick = true;
    private Thread clickThread;
    private String root_path;
    private boolean isRecord = false;
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
    ;
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                if (mMediaRecorder != null) {
                    mMediaRecorder.stop();
                    mMediaRecorder.release();
                    mMediaRecorder = null;
                }
                if (mPreviewSession != null) {
                    mPreviewSession.close();
                }
                if (cameraDevice != null) {
                    cameraDevice.close();
                }
                initCamera();
            }
        }
    };

    public RoadRecordService() {
    }
    public static void start(Context context)
    {
        Intent intent = new Intent(context, RoadRecordService.class);
        context.startService(intent);// 启动服务
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
        root_path = getExternalFilesDir("") + "/video";
        initSurface();
        HandlerThread handlerThread = new HandlerThread("Camera2Demo");
        handlerThread.start();
        mChildHandler = new Handler(handlerThread.getLooper());
        initSessionCaptureCallback();
        initSessionStateCallback();
    }

    @SuppressLint("MissingPermission")
    private void initCamera() {
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            cameraManager.openCamera(camera_id + "", new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    cameraDevice = camera;

                    createBuild();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    stopSelf();
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    stopSelf();
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void initSurface() {
        windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        TextView textView = new TextView(this);
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                150, 70,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT
        );
        textView.setText("开始录制");
        textView.setBackgroundColor(Color.RED);
        textView.setGravity(Gravity.CENTER);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "onClick=====");
                if (isRecord) {
                    isRecord = false;
                    stopRecord();
                    textView.setText("开始录制");
                } else {
                    isRecord = true;
                    initCamera();
                    textView.setText("结束录制");
                }
            }
        });
        layoutParams.gravity = Gravity.RIGHT | Gravity.TOP;

//        windowManager.addView(textView, layoutParams);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        video_duration = intent.getIntExtra("duration", 10000);
        camera_id = intent.getIntExtra("id", 0);
        camera_w = intent.getIntExtra("width", 1280);
        camera_h = intent.getIntExtra("height", 720);
        Log.i(TAG, "onStartCommand = " + video_duration + ";" + camera_id + ";" + camera_w + ";" + camera_h);
        initCamera();
        startThread();
        return super.onStartCommand(intent, flags, startId);
    }

    private void startThread() {
        clickThread = new Thread(new Runnable() {
            @Override
            public void run() {
                int j = 0;
                while (isClick) {
                    Log.i(TAG, "thread = " + j);
                    j++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        clickThread.start();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private void setUpMediaRecorder() {
        mMediaRecorder = new MediaRecorder();
        //设置用于录制的音源
//        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //开始捕捉和编码数据到setOutputFile（指定的文件）
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        //设置在录制过程中产生的输出文件的格式
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        //设置输出文件的路径
        mMediaRecorder.setOutputFile(getVideoPath());
        //设置录制的视频编码比特率
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        //设置要捕获的视频帧速率
        mMediaRecorder.setVideoFrameRate(25);
        //设置要捕获的视频的宽度和高度
        mMediaRecorder.setVideoSize(camera_w, camera_h);
        //设置视频编码器，用于录制
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        //设置audio的编码格式
//        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        try {
            mMediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getVideoPath() {
        File pathFile = new File(root_path);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        String videoPath = root_path + "/" + simpleDateFormat.format(new Date()) + ".mp4";
        Log.i(TAG, "videoPath = " + videoPath);
        File videoFile = new File(videoPath);
        try {
            videoFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return videoPath;
    }

    private void createBuild() {
        setUpMediaRecorder();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            try {
                mPreviewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
                List<Surface> surfaces = new ArrayList<>();
                Surface recorderSurface = null;
                recorderSurface = mMediaRecorder.getSurface();
                surfaces.add(recorderSurface);
                mPreviewBuilder.addTarget(recorderSurface);
                // 一旦会话开始，我们就可以更新UI并开始录制
                cameraDevice.createCaptureSession(surfaces, mSessionStateCallback, mChildHandler);
                startRecord();
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private void startRecord() {
        Log.i(TAG, "startRecord = " + i);
        i++;
        mMediaRecorder.start();
        deleteFile();
        handler.sendEmptyMessageDelayed(0, video_duration);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void initSessionStateCallback() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mSessionStateCallback = new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    mPreviewSession = session;
                    try {
                        //执行重复获取数据请求，等于一直获取数据呈现预览画面，mSessionCaptureCallback会返回此次操作的信息回调
                        mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mChildHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }

                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                }
            };
        }
    }

    private void initSessionCaptureCallback() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
                    super.onCaptureStarted(session, request, timestamp, frameNumber);
                }

                @Override
                public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
                    super.onCaptureProgressed(session, request, partialResult);
                }

                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                }

                @Override
                public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
                    super.onCaptureFailed(session, request, failure);
                }
            };
        }
    }

    private void deleteFile() {
        File rootFile = new File(root_path);
        File[] childFiles = rootFile.listFiles();
        if (childFiles.length > 10) {
            long time = 0;
            File delFile = null;
            for (int j = 0; j < childFiles.length; j++) {
                File childFile = childFiles[j];
                String name = childFile.getName();
                String timeStr = name.substring(0, name.lastIndexOf("."));
                Log.i(TAG, "child name = " + timeStr);
                try {
                    long t = simpleDateFormat.parse(timeStr).getTime();
                    if (time == 0) {
                        time = t;
                        delFile = childFile;
                    }
                    if (t < time) {
                        time = t;
                        delFile = childFile;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            if (delFile != null) {
                Log.i(TAG, "delFile = " + delFile.getPath());
                delFile.delete();
            }
        } else {
            Log.i(TAG, "file length = " + childFiles.length);
        }
    }

    private void stopRecord() {

            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
                mMediaRecorder.release();
            }

        if (mPreviewSession != null) {
            mPreviewSession.close();
        }
        if (cameraDevice != null) {
            cameraDevice.close();
        }
    }

    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        stopRecord();
        if (clickThread != null) {
            isClick = false;
        }
        super.onDestroy();
    }
}